﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ReAnimation.Infrastructure.Services.DomainFactories.Interfaces;
using ReAnimation.Domain;
using Castle.DynamicProxy;
using ReAnimation.Helpers.DynamicProxy;
using ReAnimation.DAL.RepositoryInterfaces;

namespace ReAnimation.Infrastructure.Services.DomainFactories
{
    public class MoleculeFactory: IMoleculeFactory
    {
        private static ProxyGenerator _proxyGenerator = new ProxyGenerator();
        private IAtomDescriptionRepository _repository;

        public MoleculeFactory(IAtomDescriptionRepository respository)
        {
            _repository = respository;
        }

        #region IMoleculeFactory Members

        public Molecule CreateMolecule()
        {
            return _proxyGenerator.CreateClassProxy<Molecule>(new[] { new EventsSourceInterceptor() });
        }

        public Molecule CloneMolecule(Molecule molecule)
        {
            Molecule newMolecule = CreateMolecule();
           
            newMolecule.Name = molecule.Name.Clone() as String;
            newMolecule.TransformMatrix = molecule.TransformMatrix;
            newMolecule.MoleculeZMatrix = CloneZMatrix(molecule.MoleculeZMatrix);
           
            newMolecule.Atoms = molecule.Atoms.Select((a) =>
                {
                    return CloneAtom(a);
                }).ToList<Atom>();

            newMolecule.Links = molecule.Links.Select((l) =>
                {
                    return CloneLink(l);
                }).ToList<Link>();

            return newMolecule;
        }

        #endregion

        private Link CloneLink(Link link)
        {
            Link newLink = new Link();

            newLink.Atom1 = CloneAtom(link.Atom1);
            newLink.Atom2 = CloneAtom(link.Atom2);
            newLink.LinkType = link.LinkType;

            return newLink;
        }

        private Atom CloneAtom(Atom atom)
        {
            Atom newAtom = new Atom();

            newAtom.AtomDescription = CloneAtomDescription(atom.AtomDescription);
            newAtom.Position = atom.Position;

            return newAtom;
        }

        private ZMatrix CloneZMatrix(ZMatrix zMatrix)
        {
            ZMatrix newZMatrix = new ZMatrix();
            newZMatrix.ZMatrixLines = zMatrix.ZMatrixLines.Select((l) =>
                {
                    return CloneZMatrixLine(l);
                }).ToList<ZMatrixLine>();
            return newZMatrix;
        }

        private ZMatrixLine CloneZMatrixLine(ZMatrixLine line)
        {
            ZMatrixLine newZMatrixLine = new ZMatrixLine();
            
            newZMatrixLine.AngleConnect = line.AngleConnect;
            newZMatrixLine.AtomConnect = line.AtomConnect;
            newZMatrixLine.AtomDescription = CloneAtomDescription(line.AtomDescription);
            newZMatrixLine.BondAngle = line.BondAngle;
            newZMatrixLine.BondDistance = line.BondDistance;
            newZMatrixLine.DihedralAngle = line.DihedralAngle;
            newZMatrixLine.DihedralConnect = line.DihedralConnect;

            return newZMatrixLine;
        }

        private AtomDescription CloneAtomDescription(AtomDescription atomDescription)
        {
            return _repository.GetByName(atomDescription.Name);
/*
            AtomDescription newAtomDescription = new AtomDescription();

            newAtomDescription.Name = atomDescription.Name.Clone() as String;
            newAtomDescription.Radius = atomDescription.Radius;
            newAtomDescription.Color = atomDescription.Color;

            return newAtomDescription;*/
        }

        
    }
}
